iT邦幫忙

2021 iThome 鐵人賽

0
自我挑戰組

Be friend with JavaScript系列 第 32

React 運作原理 & JSX

  • 分享至 

  • xImage
  •  

React 運作原理

在原生的 JavaScript 裡,我們會操作 DOM 來修改網頁程式碼,但這麼做會很容易不小心改到不需要變動的地方,React 解決了這件事,讓 React 程式碼在更新 DOM 之前,先用 JavaScript 製造出虛擬的 DOM - Virtual DOM,利用這個 Virtual DOM 模擬所有更新後應該要長的樣子,設計一個特殊的 Diff 演算法去比較當前的 DOM 和 模擬出的虛擬 DOM 的差別,最後 React 只會去修改有不一樣的地方,避免資源的浪費。

首先來看看下面這三行程式碼:
第一行為導入 React
第二行為導入 ReactDOM
第三行為開發 React 程式的進入點,讓所有 React 程式碼透過 ReactDOM 提供的 render 函式綁定到 HTML 裡,render 的第一個參數是要渲染到畫面上的元素,第二個參數決定元素要放到哪個 HTML 元素內。

// 獲得 React & ReactDom module
import React from "react";
import ReactDOM from "react-dom";
// 渲染到畫面上
ReactDom.render(<div>Hello, World></div>, document.querySelector("#root"));

第三行將 <div>Hello, World></div> 綁定到 <div id="root"></div>,而這個 html 檔案會在 public 資料夾裡面的 index.html,打開會發現 body 裡面有個 id 為 root 的 div 元素,這就是我們綁定 React 程式的地方,所有專案的元素都會被 React 包進 index.html 的 <div id="root"></div> 裡面。

下面只是為了理解 React 背後的原理,所以使用 React.createElement,但平常不會使用這些做法,而會使用 JSX

  • 製作單一元素
    React.createElement("HTML tag", css設定, "HTML tag 的內容")
    index.js
// 獲得 React & ReactDom module
import React from "react";
import ReactDOM from "react-dom";
// 製作 h1
function App() {
  return React.createElement("h1", null, "This is React App.");
}
// ReactDOM.render(渲染的內容,要渲染的位置)
ReactDom.render(React.createElement(App), document.querySelector("#root"));

由此可知 React 的原理為,用 function 製造出 Element,再選定 HTML 文件的某個地方讓創造出來的 Element 顯示到那裡。

  • 製作多個元素

因為一個 function 不能 return 好幾個值,所以要製作多個 html 標籤的話,在 React.createElement() 裡面的第 3 個參數要是一個 Array。

// 獲得 React & ReactDom module
import React from "react";
import ReactDOM from "react-dom";
// 製作 div,裡面放 h1,p,button
function App() {
  return React.createElement("div", null, [
    React.createElement("h1", { style: { color: "red" } }, "My Profile."),
    React.createElement("p", null, "My Name is Helen."),
    React.createElement("button", null, "Check my profile."),
  ]);
}
// ReactDOM.render(渲染的內容,要渲染的位置)
ReactDom.render(React.createElement(App), document.querySelector("#root"));


上面的例子使用了複雜的 JavaScript 建構出 React component,為了使開發更有效率,我們會需要 JSX。

JSX

假如我們寫這樣的 code:const h1 = <h1>Hello world</h1>,這樣運作時根本不會起作用,因為在 JavaScript 裡不能包含 HTML,所以當這樣寫的時候瀏覽器看不懂,而 JSX 就是讓我們在寫 React 時,可以把 JavaScript 寫得很像 HTML,讓我們在 JavaScript 裡可以使用標籤式的語法來寫 React,且內建 Babel 功能,會自動將 JSX 編譯成瀏覽器能理解的 JavaScript(JSX 會被編譯成前面提到的 React.createElement 的作法)。

  • 要注意 2 件事:
  1. 所有的 function 只能 return 一個值,所以當裡面放很多個元素時,就要用一個封閉的標籤包起來,例如 div。
  2. function 的名稱開頭一定要是大寫,不可為小寫,大寫才會被當成 component,寫小寫的話會被瀏覽器以為是 HTML tag。

將上面 React.createElement 的程式碼改為 JSX :

// 獲得 React & ReactDom module
import { div } from "prelude-ls";
import React from "react";
import ReactDOM from "react-dom";

// JSX
function App() {
  return (
    <div>
      <h1 style={{ color: "red" }}>My Profile.</h1>
      <p>My Name is Helen.</p>
      <button>Check my profile.</button>
    </div>
  );
}
// ReactDOM.render(渲染的內容,要渲染的位置)
ReactDom.render(<App />, document.querySelector("#root"));

  • React Fragment
    上面的內容有提到,如果想要在 React 同時渲染多個元素時,我們必須將元素包在一個封閉的標籤裡面,但這種作法會產生許多沒有意義的標籤,React Fragment 可以為我們省去額外多餘的容器,使 DOM 的結構更乾淨。
    將上面的程式碼由 div 改成 React Fragment:
import { div } from "prelude-ls";
import React from "react";
import ReactDOM from "react-dom";

function App() {
  return (
    <React.Fragment>
      <h1 style={{ color: "red" }}>My Profile.</h1>
      <p>My Name is Helen.</p>
      <button>Check my profile.</button>
    </React.Fragment>
  );
}

ReactDom.render(<App />, document.querySelector("#root"));

也可以使用 React.Fragment 的簡寫語法:

import { div } from "prelude-ls";
import React from "react";
import ReactDOM from "react-dom";

function App() {
  return (
    <>
      <h1 style={{ color: "red" }}>My Profile.</h1>
      <p>My Name is Helen.</p>
      <button>Check my profile.</button>
    </>
  );
}

ReactDom.render(<App />, document.querySelector("#root"));

使用 React.Fragment 後,如果去檢視 DOM,會發現並沒有渲染成任何標籤

<div id="root">
  略
<div/>
  • 在 JSX 裡加入 CSS 的方式

在 tag 裡加入 style={{ }},第一個括號表示傳參數,第二個表示參數裡的 CSS 設定
例如:<h1 style={{ color: "red" }}>My Profile.</h1>

  • 在 JSX 裡,寫入 JavaScript 需要使用大括號 { } 包覆

例如:<h1>{ title.toUpperCase() }</h1>
因為大括號裡代表寫入的 JavaScript,h1 的內容會變成 TITLE

  • className, htmlFor

因為在 JavaScript 中已經有 class 和 for,當我們在寫 JSX 時,會以 className 來表示 HTML 的 class 屬性,而以 htmlFor 表示 for。
例如:<h1 className="title">Hello World</h1>

參考資料:
一本在誠品看到的書,忘記書名是什麼了 XD


上一篇
認識 React.js
下一篇
建立 React component
系列文
Be friend with JavaScript39
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言